1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package com.google.common.reflect;
18
19 import static com.google.common.base.Preconditions.checkNotNull;
20
21 import com.google.common.annotations.Beta;
22 import com.google.common.base.Function;
23 import com.google.common.collect.ForwardingMap;
24 import com.google.common.collect.ForwardingMapEntry;
25 import com.google.common.collect.ForwardingSet;
26 import com.google.common.collect.Iterators;
27 import com.google.common.collect.Maps;
28
29 import java.util.Iterator;
30 import java.util.Map;
31 import java.util.Set;
32
33 import javax.annotation.Nullable;
34
35
36
37
38
39
40
41
42 @Beta
43 public final class MutableTypeToInstanceMap<B> extends ForwardingMap<TypeToken<? extends B>, B>
44 implements TypeToInstanceMap<B> {
45
46 private final Map<TypeToken<? extends B>, B> backingMap = Maps.newHashMap();
47
48 @Nullable
49 @Override
50 public <T extends B> T getInstance(Class<T> type) {
51 return trustedGet(TypeToken.of(type));
52 }
53
54 @Nullable
55 @Override
56 public <T extends B> T putInstance(Class<T> type, @Nullable T value) {
57 return trustedPut(TypeToken.of(type), value);
58 }
59
60 @Nullable
61 @Override
62 public <T extends B> T getInstance(TypeToken<T> type) {
63 return trustedGet(type.rejectTypeVariables());
64 }
65
66 @Nullable
67 @Override
68 public <T extends B> T putInstance(TypeToken<T> type, @Nullable T value) {
69 return trustedPut(type.rejectTypeVariables(), value);
70 }
71
72
73 @Override public B put(TypeToken<? extends B> key, B value) {
74 throw new UnsupportedOperationException("Please use putInstance() instead.");
75 }
76
77
78 @Override public void putAll(Map<? extends TypeToken<? extends B>, ? extends B> map) {
79 throw new UnsupportedOperationException("Please use putInstance() instead.");
80 }
81
82 @Override public Set<Entry<TypeToken<? extends B>, B>> entrySet() {
83 return UnmodifiableEntry.transformEntries(super.entrySet());
84 }
85
86 @Override protected Map<TypeToken<? extends B>, B> delegate() {
87 return backingMap;
88 }
89
90 @SuppressWarnings("unchecked")
91 @Nullable
92 private <T extends B> T trustedPut(TypeToken<T> type, @Nullable T value) {
93 return (T) backingMap.put(type, value);
94 }
95
96 @SuppressWarnings("unchecked")
97 @Nullable
98 private <T extends B> T trustedGet(TypeToken<T> type) {
99 return (T) backingMap.get(type);
100 }
101
102 private static final class UnmodifiableEntry<K, V> extends ForwardingMapEntry<K, V> {
103
104 private final Entry<K, V> delegate;
105
106 static <K, V> Set<Entry<K, V>> transformEntries(final Set<Entry<K, V>> entries) {
107 return new ForwardingSet<Map.Entry<K, V>>() {
108 @Override protected Set<Entry<K, V>> delegate() {
109 return entries;
110 }
111 @Override public Iterator<Entry<K, V>> iterator() {
112 return UnmodifiableEntry.transformEntries(super.iterator());
113 }
114 @Override public Object[] toArray() {
115 return standardToArray();
116 }
117 @Override public <T> T[] toArray(T[] array) {
118 return standardToArray(array);
119 }
120 };
121 }
122
123 private static <K, V> Iterator<Entry<K, V>> transformEntries(Iterator<Entry<K, V>> entries) {
124 return Iterators.transform(entries, new Function<Entry<K, V>, Entry<K, V>>() {
125 @Override public Entry<K, V> apply(Entry<K, V> entry) {
126 return new UnmodifiableEntry<K, V>(entry);
127 }
128 });
129 }
130
131 private UnmodifiableEntry(java.util.Map.Entry<K, V> delegate) {
132 this.delegate = checkNotNull(delegate);
133 }
134
135 @Override protected Entry<K, V> delegate() {
136 return delegate;
137 }
138
139 @Override public V setValue(V value) {
140 throw new UnsupportedOperationException();
141 }
142 }
143 }